/**
 * @file boards\stm32l051kx\bsp\bsp_key1.c
 *
 * Copyright (C) 2023
 *
 * bsp_key1.c is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author HinsShum hinsshum@qq.com
 *
 * @encoding utf-8
 */

/*---------- includes ----------*/
#include "bsp_motor.h"
#include "gd32f30x_gpio.h"
#include "gd32f30x_timer.h"
#include "gpio_group.h"


/*---------- macro ----------*/
#define GPIO_PORT_MOTOR1 GPIOA
#define GPIO_PIN_MOTOR1 GPIO_PIN_6

#define GPIO_PORT_MOTOR2 GPIOC
#define GPIO_PIN_MOTOR2 GPIO_PIN_6

/*---------- type define ----------*/
typedef enum { motor_left = 0, motor_right } motor_id_t;
/*---------- variable prototype ----------*/
/*---------- function prototype ----------*/
static bool bsp_init(void);
static void bsp_deinit(void);
static unsigned char bsp_get(unsigned char xx);
static void bsp_set(unsigned char xx, unsigned char val);
static uint32_t frequency = 2000;
static uint32_t preload_value = 1000;
/*---------- variable ----------*/
static gpio_group_describe_t motor = { .group_name = "motor",
                                      .ops.init = bsp_init,
                                      .ops.deinit = bsp_deinit,
                                      .ops.get = NULL,
                                      .ops.set = bsp_set,
                                      .group_num_max = 2,
                                      .user_date = NULL,
                                      .user_date_special = NULL };
DEVICE_DEFINED(motor, gpio_group, &motor);

/*---------- function ----------*/
static bool bsp_init(void) {
//    timer_oc_parameter_struct timer_oc_param;
//    timer_parameter_struct timer_param;
//    uint32_t timer_clock = rcu_clock_freq_get(CK_APB1);
//    uint32_t prescaler = timer_clock / (preload_value * frequency) - 1;
//    uint32_t period = timer_clock / (preload_value * (prescaler + 1)) - 1;

//    rcu_periph_clock_enable(RCU_GPIOA);
//    rcu_periph_clock_enable(RCU_GPIOC);
//    rcu_periph_clock_enable(RCU_AF);
//    rcu_periph_clock_enable(RCU_TIMER7);
//    rcu_periph_clock_enable(RCU_TIMER2);

//    gpio_init(GPIO_PORT_MOTOR1, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,
//        GPIO_PIN_MOTOR1);
//    gpio_init(GPIO_PORT_MOTOR2, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,
//        GPIO_PIN_MOTOR2);

//    timer_deinit(TIMER7);
//    timer_deinit(TIMER2);
//    /* init timert */
//    timer_struct_para_init(&timer_param);
//    timer_param.prescaler = prescaler;
//    timer_param.alignedmode = TIMER_COUNTER_UP;
//    timer_param.period = period;
//    timer_param.clockdivision = TIMER_CKDIV_DIV1;
//    timer_init(TIMER7, &timer_param);
//    timer_init(TIMER2, &timer_param);
//    /* timerx pwm configuration in pwm1 */
//    timer_oc_param.ocpolarity = TIMER_OC_POLARITY_LOW;
//    timer_oc_param.outputnstate = TIMER_CCX_ENABLE;
//    timer_oc_param.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
//    timer_oc_param.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
//    timer_oc_param.outputnstate = TIMER_CCXN_DISABLE;
//    timer_oc_param.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;

//    timer_channel_output_config(TIMER2, TIMER_CH_1, &timer_oc_param);
//    timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_1, preload_value);
//    timer_channel_output_mode_config(TIMER2, TIMER_CH_1, TIMER_OC_MODE_PWM0);
//    timer_channel_output_shadow_config(TIMER2, TIMER_CH_1,
//        TIMER_OC_SHADOW_DISABLE);

//    timer_channel_output_config(TIMER7, TIMER_CH_1, &timer_oc_param);
//    timer_channel_output_pulse_value_config(TIMER7, TIMER_CH_1, preload_value);
//    timer_channel_output_mode_config(TIMER7, TIMER_CH_1, TIMER_OC_MODE_PWM0);
//    timer_channel_output_shadow_config(TIMER7, TIMER_CH_1,
//        TIMER_OC_SHADOW_DISABLE);

//    timer_enable(TIMER2);
//    timer_primary_output_config(TIMER7, ENABLE);
//    timer_auto_reload_shadow_disable(TIMER7);

//    timer_channel_output_pulse_value_config(TIMER7, TIMER_CH_1, 100);
//    timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_1, 1000);

    return true;
}

static void bsp_deinit(void) {

//    rcu_periph_clock_enable(RCU_GPIOC);
//    rcu_periph_clock_enable(RCU_GPIOA);
//    rcu_periph_clock_enable(RCU_AF);

//    gpio_init(GPIO_PORT_MOTOR1, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ,
//        GPIO_PIN_MOTOR1);
//    gpio_init(GPIO_PORT_MOTOR2, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ,
//        GPIO_PIN_MOTOR2);

//    timer_deinit(TIMER7);
//    timer_deinit(TIMER2);
}

static void bsp_set(unsigned char xx, unsigned char val) {
    uint32_t pulse_width = (uint32_t)((preload_value + 1) * val / 100);
    if (val == 0)
    {
//        gpio_bit_reset(GPIO_PORT_MOTOR1, GPIO_PIN_MOTOR1);
//        gpio_bit_reset(GPIO_PORT_MOTOR2, GPIO_PIN_MOTOR2);
        return;
    }
//    if (xx == motor_left) {
//        timer_channel_output_pulse_value_config(TIMER7, TIMER_CH_1, pulse_width);
//    gpio_bit_set(GPIO_PORT_MOTOR1, GPIO_PIN_MOTOR1);
//    }
//    else if (xx == motor_right) {
//        timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_1, pulse_width);
//    gpio_bit_set(GPIO_PORT_MOTOR2, GPIO_PIN_MOTOR2);
//    }
}

static unsigned char bsp_get(unsigned char xx) {
    unsigned char Tgroup_sta = 0;

    return Tgroup_sta;
}
